#======================================================================
# Product:      KnowledgeEngine (Plone Version)
#
# File:         metaWeblogAPI.py
#
# Copyright:    Copyright (c) 2006, Faulkner Technologies
#
# Author:       John Meredith
#
# Description:  Implements http://www.xmlrpc.com/metaWeblogApi
#======================================================================


#======================================================================
# KnowledgeEngine Imports
#----------------------------------------------------------------------
from BloggerAPI import *


#======================================================================
# Zope Library Imports
#----------------------------------------------------------------------


#======================================================================
# Python Library Imports
#----------------------------------------------------------------------
import os
import sys
import unittest


#======================================================================
# metaWeblog class
#----------------------------------------------------------------------
class metaWeblogAPI (BloggerAPI):
    """
        Implements the metaWeblog API, which is an extension of
        the BloggerAPI
    """

    # Some meta-data for the blog client
    TITLE = "metaWeblogAPI (BloggerAPI ext.)"
    
    #---------------------------------------------------------------------------
    # Flag to identify whether this API allows for anonymous posting to blogs
    ALLOW_ANONYMOUS = False


    def getPost(self, postId):
        """
            Gets a post by postId
        """

        server = self.getServer()

        return server.metaWeblog.getPost(self._APPKEY, str(postId), self.username, self.password)


    def createPost(self, **args):
        """
            Makes a new post to a designated blog. Optionally, will publish the blog after making the post.
        """

        # Setup default newPost parameters
        config = {
            'publish' : True
        }
        config.update(args)

        # If we don't have a blogId, try and find it
        if not config.has_key('blogId') or not config['blogId']:
            # Use the first blog we find as a default
            userBlogsList = self.getUsersBlogs()
            config['blogID'] = userBlogsList[0]['blogid']


        # Check that we have some content
        if not config.has_key('content') and not config['content']:
            raise TypeError, "A blog post must contain some form of content/body text."

        # Assemble our post
        post = {}
        post['description'] = "<member><name>description</name><value>%s</value></member>" % str(config['content'])

        # Some blogs can take a category as well
        if config.has_key('category') and config['category']:
            post['categories'] = "<member><name>categories</name><value>%s</value></member>" % str(config['category'])

        # If we have a title, wrap it and add to content
        if config.has_key('title') and config['title']:
            post['title'] = "<member><name>title</name><value>%s</value></member>" % str(config['title'])


        # Flatten the post dictionary to a single string
        content = ""
        for item in post.values():
            content += item
        content = "<struct>%s</struct>" % content

        print "Content: %s" % (content, )

        # Now do the magic to create our post
        server = self.getServer()
        postId = server.metaWeblog.newPost(
            str(config['blogId']),
            str(self.username),
            str(self.password),
            str(content),
            bool(config['publish'])
        )

        return postId


    def editPost(self, postId, **args):
        """
            Edits a given post. Optionally, will publish the blog after making the edit.
        """

        # Setup default newPost parameters
        config = {
            'publish' : True
        }
        config.update(args)

        # Check we've been given a post ID
        if not postId:
            raise TypeError, 'Must specify the ID of the post you wish to edit'

        # Check that we have some content
        if not config.has_key('content') and not config['content']:
            raise TypeError, "A blog post must contain some form of content/body text."

        post = {}
        post['description'] = config['content']

        # Some blogs can take a category as well
        if config.has_key('category') and config['category']:
            post['categories'] = str(config['category'])

        # If we have a title, wrap it and add to content
        if config.has_key('title') and config['title']:
            post['title'] = str(config['title'])
        
        content = ""
        for item in map(lambda k: "<%s>%s</%s>" % (k[0], k[1], k[0]), post.items()):
            content += item

        # Now do the magic to create our post
        server = self.getServer()
        
        postId = server.metaWeblog.editPost(
            self._APPKEY,
            str(postId),
            str(self.username),
            str(self.password),
            str(content),
            bool(config['publish'])
        )

        return postId


#======================================================================
# Register metaWeblog client with the action
#----------------------------------------------------------------------
try:
    from Products.KnowledgeEngine.Actions.BlogPost.Clients import registerBlogClient
    registerBlogClient(metaWeblogAPI, metaWeblogAPI.TITLE)
except Exception, e:
    pass

#======================================================================
# Unit Tests
#----------------------------------------------------------------------
class BloggerAPITests(unittest.TestCase):
    def setUp(self):
        self.client = metaWeblogAPI(username='admin', password='Lmmsoht', url='http://127.0.0.1/wordpress/xmlrpc.php')

    
    def testConnection(self):
        """
            Test that the connection is valid. Requires a blog :-)
        """

        # Check connection can be established
        self.failUnless(self.client.isValidConnection())


    def testUsersBlogs(self):
        """
            Check that we can get a list of the users blogs
        """
        
        self.failUnless(self.client.getUsersBlogs())
        
        posts = self.client.getRecentPosts(28316670, 5)
        self.failUnless(posts)


    def testPosting(self):
        """
            Test that we can create a new post
        """

        newPost = {
            'blogId' : '28316670', # John's 'Vdyzz' test blog
            'content' : "New post content",
            'category' : 2,
            'title' : 'A test post'
        }

        # Create a post
        postId = self.client.createPost(**newPost)
        self.failUnless(postId)

        # Edit the post
        self.failUnless(self.client.editPost(postId, content="This has been edited", publish=True))

        # Grab our post by Id and check that it's been edited
        post = self.client.getPost(postId)
        self.failUnless(post)
        self.failUnless(post['content'] == "This has been edited")

        # Try to delete out post
        self.failUnless(self.client.deletePost(postId))


if __name__ == '__main__':
    unittest.main()
